package com.rtsapp.server.logger.format;

import com.rtsapp.server.logger.spi.LogEvent;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 格式化时间
 * 线程安全的
 */
public class DateFormat implements ILogFormat {

    private static final int countThreshold = 1000;


    private volatile short count = 0;

    //SimpleDateFormat 不是线程安全的
    private final SimpleDateFormat sdf;

    /**
     * 当前的毫秒数
     */
    private volatile long currentMS = 0;
    /**
     * 下一秒的整秒毫秒数
     */
    private volatile long nextSecMS = 0;
    /**
     * 当前这一秒的时间, 被格式化的结果
     */
    private volatile String currentSecFormat = null;

    /***
     * 运行中
     */
    private static volatile boolean running = true;

    private final ReentrantLock lock = new ReentrantLock();

    public DateFormat(String datePattern) {
        this.sdf = new SimpleDateFormat( datePattern );
        setCurrent();
        final Thread updater = new Thread( new DateFormatClockThread() , "DateFormatClockThread" );
        updater.setDaemon( true );
        updater.start();
    }


    public static void stop(){
        running = false;
    }

    @Override
    public void format(StringBuilder sb, LogEvent e) {

        // 如果日志次数够，同步时间
        if( count++ >  countThreshold ){
            setCurrent();
            count = 0;
        }

        // 如果到了下一秒之后
        if( currentMS >=  nextSecMS ){
            //进行时间变更
            try {
                lock.lock();

                //如果有必要更新
                if( currentMS >= nextSecMS ){

                    // 计算下一秒
                    if( currentMS % 1000 == 0 ){
                        nextSecMS = currentMS + 1000;
                    }else {
                        nextSecMS = (long) (Math.ceil(currentMS / 1000.0) * 1000);
                    }

                    // 计算当前格式化
                    currentSecFormat = sdf.format( new Date( currentMS  ) );
                }
            }finally {
                lock.unlock();
            }
        }

        //返回格式
        sb.append( currentSecFormat );
    }


    private void setCurrent(){
        currentMS = System.currentTimeMillis();
    }


    private class DateFormatClockThread implements Runnable{

        @Override
        public void run() {
            while ( running ){
                setCurrent();
                LockSupport.parkNanos( 1000 * 1000 );
            }
        }
    }

}
